#ifndef HANDTRACKER_LKHSVCD_HPP
#define HANDTRACKER_LKHSVCD_HPP

#include <cv.h>
#include <highgui.h>

//NOTE: opencv2 header
#include "opencv2/video/tracking.hpp"

#include "AbstractHandTracker.hpp"
#include "abstractProbabilityTransformer.hpp"
#include "abstractFilter.hpp"
#include "GestureClassifier.hpp"

//LEGEND:
//LKGREY : tracking uses pyrLK on greyscale image
//MS: tracking is then updated with meanshift
	//BP: which uses backprojection
		//FOx: which uses and OpenFilter which iterates x times (x is variable)

class HandTrackerLKHSVCD : AbstractHandTracker {
public:
	static AbstractHandTracker* init( bool	useHSV, float meanshiftWeightFactor, float processNoiseCovScalar, float measurementNoiseCovScalar,
									 float shortDistIgnoreThreshold, cv::Rect trackingRect, cv::Mat& initImage, cv::Ptr< GeometricGestureClassifier > gClassifier );

	cv::Rect track(cv::Mat& nextImage );
	
protected:
	cv::Rect trackingRect;
	cv::Mat imgA;
	cv::Mat imgB;
	
private:
	
	HandTrackerLKHSVCD( bool useHSV, float meanshiftWeightFactor, float shortDistIgnoreThreshold, cv::Rect trackingRect, cv::Ptr< GeometricGestureClassifier > gClassifier, float measurementNoiseCovScalar );
	
	cv::Point2f initialLocationGuess( const cv::Mat& probImage );
	
	static void forceInside( const cv::Size& outerFrame, cv::Rect& innerRect );
	
	cv::Ptr< GeometricGestureClassifier > gClassifier;
	
	cv::Mat* imgPtr1;
	cv::Mat* imgPtr2;
	
	
	cv::KalmanFilter positionKF;
	
	float prevX;
	float prevY;	
	
	bool useHSV;
	
	vector<cv::Point2f> corners;
	vector<cv::Point2f> potentiallyReusedCorners;
	vector<cv::Point2f> reusedCorners;
	//FIX: when done with visualisation, update this to use swap of some sort? Could save some copying of data
	
	//FIX : Test these values //FULLTEST
	int maxCorners;
	int minCornersToTrack;
	double qualityLevel;
	double minDistance;
	
	float meanshiftWeightFactor;
	
	float cornerReuseErrorThreshold;
	
	float shortDistIgnoreThreshold; //FIXNOW should be scale dependent? -- needs FULL TESTING //FIXNOW //FULLTEST
	float accelerationIgnoreThreshold;
	
	vector<cv::Point2f> nextCorners;
	vector<uchar> cornersFound;
	vector<float> cornerErrors;
	
	
	float measurementNoiseCovScalar;
	

};

#endif
	
	
	